package paim.wingchun.controller;


import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.lang.reflect.Field;
import java.util.List;
import java.util.logging.Level;

import javax.swing.JComponent;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import paim.wingchun.app.WC_Log;
import paim.wingchun.controller.eventos.DefaultFiltrarEvent;
import paim.wingchun.model.pojos.Erro;
import paim.wingchun.model.pojos.Pojo;
import paim.wingchun.view.AbstractView;
import paim.wingchun.view.AbstractView.Estado;
import paim.wingchun.view.SelecionarView;
import paim.wingchun.view.componentes.table.WC_TableModel;

import static paim.wingchun.app.Reflections.getField;
import static paim.wingchun.app.Reflections.getValorField;

/** @author temujin Jun 5, 2011 */
public class Selecionar<P extends Pojo> extends AbstractListController<P, SelecionarView<P>> implements
                TableModelListener {

    @SuppressWarnings("unused")
    private int selectionMode = ListSelectionModel.SINGLE_SELECTION;

    public <P2 extends Pojo, V2 extends AbstractView<P2>, C extends AbstractController<P2, V2> & HasConstrutor> Selecionar(
                    C parent, P2 parentPojo, JComponent parentComponent, Class<P> pClass) {
        super(parent, parentPojo, parentComponent, pClass);
    }

    @Override
    protected void apos_addListeners() {
        super.apos_addListeners();
        getVisao().addListener(new DefaultFiltrarEvent(getVisao()));

        getVisao().getTable().getModel().addTableModelListener(this);

        getVisao().getJCheckBox().addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if ( e.getStateChange() == ItemEvent.SELECTED )
                    selectAll();
                else if ( e.getStateChange() == ItemEvent.DESELECTED )
                    deselectAll();
            }
        });

        getVisao().getTable().getSelectionModel()
                        .addListSelectionListener(e -> {/* System.out.println("valueChanged"); */});
    }

    protected void deselectAll() {
        ((WC_TableModel) getVisao().getTable().getModel()).deselectAll();
    }

    protected void selectAll() {
        ((WC_TableModel) getVisao().getTable().getModel()).selectAll();
    }

    @Override
    public boolean isModal() {
        // TODO deveria impementar em controlador.setup um modal sem controlador pai. ok
        return true;
    }

    @Override
    protected void apos_setObjeto(Object objeto) {
        /* por padrao, manda deixar selecionado os objetos que estao incluido no controlador pai */
        try {
            /* busca o field da classe pai listado na selecao */
            Field field = getField(getPojoPai().getClass(), getpClass());
            /* pega instancia */
            Object selecionar = getValorField(getPojoPai(), field);
            /* manda selecionar no table */
            getVisao().getTable().setSelecao(selecionar);

            getVisao().setEditando(true);
        }
        catch ( Exception e ) {
            WC_Log.getInstancia().getlogger().log(Level.SEVERE, e.getMessage(), e);
        }
    }

    @Override
    protected Estado c_confirmar(Object objeto, List<Erro> erros) throws Exception {
        /* nao faz nada, apenas diz que confirmou */
        return Estado.Confirmado;
    }

    @Override
    protected void devolver(Object pojo) throws Exception {
        /* se ambos controladores tem mesma sessao */
        ((HasConstrutor) getPai()).recebeObjeto(getVisao().getTable().getSelecao(), getComponentPai());
    }

    public Object getSelecao() {
        return getVisao().getTable().getSelecao();
    }

    @Override
    public void tableChanged(TableModelEvent e) {
        /* verificando se eh mesmo a tabela que eu quero */
        WC_TableModel model = (WC_TableModel) e.getSource();
        if ( !getVisao().getTable().getModel().equals(model) )
            return;

        Object valorNovo = model.getValueAt(e.getFirstRow(), e.getColumn());
        Object valorAntigo = !(Boolean) valorNovo;

        if ( e.getType() == TableModelEvent.UPDATE ) {
            /* notifica mudanca */
            fire(new WC_Event(Eventos.ALTERANDO, getPojoPai(), valorAntigo, valorNovo, e, getComponentPai(),
                            e.getFirstRow()));

        }
    }

}
